package com.app.myApp.service.impl;

import com.app.myApp.dao.*;
import com.app.myApp.dataobject.*;
import com.app.myApp.service.KnowledgeService;
import com.app.myApp.utils.AuthUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.DeleteObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 知识库服务实现类
 */
@Service
public class KnowledgeServiceImpl implements KnowledgeService {

    @Autowired
    private SystemKnowledgeBasesDAO systemKnowledgeBasesDAO;

    @Autowired
    private KnowledgeBasesDAO knowledgeBasesDAO;

    @Autowired
    private KnowledgeFilesDAO knowledgeFilesDAO;

    @Autowired
    private RobotAndKnowledgeBasesDAO robotAndKnowledgeBasesDAO;
    @Autowired
    private SystemKnowledgeFilesDAO systemKnowledgeFilesDAO;
    @Autowired
    private COSClient cosClient;

    @Value("${tencent.cos.bucket-name}")
    private String bucketName;

    @Value("${tencent.cos.base-url}")
    private String cosBaseUrl;

    @Override
    public List<SystemKnowledgeBasesDO> getSystemKnowledgeBases() {
        // 原有逻辑修改：关联查询系统知识库的文件列表（供管理员查看）
        List<SystemKnowledgeBasesDO> systemKbs = systemKnowledgeBasesDAO.selectAll();
        for (SystemKnowledgeBasesDO kb : systemKbs) {
            List<SystemKnowledgeFilesDO> files = systemKnowledgeFilesDAO.selectBySystemKbId(kb.getId());
            kb.setFiles(files); // 新增files字段存储文件列表（需在SystemKnowledgeBasesDO中添加）
            kb.setDocCount(files.size()); // 重置文件数量
        }
        return systemKbs;
    }

    @Override
    public List<KnowledgeBasesDO> getUserKnowledgeBases(String userEmail) {
        return knowledgeBasesDAO.selectByUserEmail(userEmail);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public KnowledgeBasesDO createKnowledgeBase(String name, String description, String userEmail, MultipartFile[] files) {
        // 生成知识库ID
        String kbId = UUID.randomUUID().toString().replace("-", "");

        // 创建知识库记录
        KnowledgeBasesDO kbDO = new KnowledgeBasesDO();
        kbDO.setId(kbId);
        kbDO.setName(name);
        kbDO.setDescription(description);
        kbDO.setUser_email(userEmail);
        kbDO.setDoc_count(files != null ? files.length : 0);
        kbDO.setCreated_at(LocalDateTime.now());
        knowledgeBasesDAO.insert(kbDO);

        // 上传文件并保存记录
        if (files != null && files.length > 0) {
            for (MultipartFile file : files) {
                uploadFileToCOSAndSave(kbId, file);
            }
        }

        return kbDO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public KnowledgeFilesDO uploadFileToKnowledgeBase(String kbId, String userEmail, MultipartFile file) {
        // 验证知识库是否存在且属于当前用户
        KnowledgeBasesDO kbDO = knowledgeBasesDAO.selectById(kbId);
        if (kbDO == null || !kbDO.getUser_email().equals(userEmail)) {
            throw new RuntimeException("知识库不存在或无权限");
        }

        // 上传文件并保存记录
        KnowledgeFilesDO fileDO = uploadFileToCOSAndSave(kbId, file);

        // 更新知识库文件计数
        kbDO.setDoc_count(kbDO.getDoc_count() + 1);
        knowledgeBasesDAO.updateDocCount(kbDO);

        return fileDO;
    }

    @Override
    public List<KnowledgeFilesDO> getFilesByKnowledgeId(String knowledgeId) {
        return knowledgeFilesDAO.selectByKnowledgeId(knowledgeId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteFile(String kbId, String fileId, String userEmail) {
        // 验证知识库权限
        KnowledgeBasesDO kbDO = knowledgeBasesDAO.selectById(kbId);
        if (kbDO == null || !kbDO.getUser_email().equals(userEmail)) {
            return false;
        }

        // 获取文件信息
        List<KnowledgeFilesDO> files = knowledgeFilesDAO.selectByKnowledgeId(kbId);
        KnowledgeFilesDO fileToDelete = files.stream()
                .filter(f -> f.getId().equals(fileId))
                .findFirst()
                .orElse(null);

        if (fileToDelete == null) {
            return false;
        }

        // 从COS删除文件
        String cosKey = fileToDelete.getPath();
        try {
            cosClient.deleteObject(bucketName, cosKey);
        } catch (Exception e) {
            // 记录日志，但继续执行数据库操作
            e.printStackTrace();
        }

        // 从数据库删除文件记录
        knowledgeFilesDAO.deleteById(fileId);

        // 更新知识库文件计数
        kbDO.setDoc_count(kbDO.getDoc_count() - 1);
        knowledgeBasesDAO.updateDocCount(kbDO);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteKnowledgeBase(String kbId, String userEmail) {
        // 验证知识库权限
        KnowledgeBasesDO kbDO = knowledgeBasesDAO.selectById(kbId);
        if (kbDO == null || !kbDO.getUser_email().equals(userEmail)) {
            return false;
        }

        // 获取该知识库下的所有文件
        List<KnowledgeFilesDO> files = knowledgeFilesDAO.selectByKnowledgeId(kbId);

        // 从COS批量删除文件
        for (KnowledgeFilesDO file : files) {
            try {
                cosClient.deleteObject(bucketName, file.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 从数据库删除文件记录
        knowledgeFilesDAO.deleteByKnowledgeId(kbId);

        // 从数据库删除知识库
        knowledgeBasesDAO.deleteById(kbId);

        return true;
    }

    @Override
    public boolean selectKnowledgeBase(Long robotId, String knowledgeBaseId, boolean isSystem) {

        int rows = robotAndKnowledgeBasesDAO.deleteByRobotId(robotId);

        RobotAndKnowledgeBasesDO relation = new RobotAndKnowledgeBasesDO();
        relation.setRobot_id(robotId);
        relation.setKnowledge_base_id(knowledgeBaseId);
        relation.setFrom(isSystem ? "system" : "personal");

        int result = robotAndKnowledgeBasesDAO.insertOrUpdate(relation);
        return result > 0;
    }

    @Override
    public boolean deselectKnowledgeBase(Long robotId) {
        int result = robotAndKnowledgeBasesDAO.deleteByRobotId(robotId);
        return result > 0;
    }

    @Override
    public RobotAndKnowledgeBasesDO getSelectedKnowledgeBase(Long robotId) {
        return robotAndKnowledgeBasesDAO.selectByRobotId(robotId);
    }

    /**
     * 上传文件到COS并保存文件记录
     */
    private KnowledgeFilesDO uploadFileToCOSAndSave(String kbId, MultipartFile file) {
        try {
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExt = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString().replace("-", "") + fileExt;

            // 构建COS中的文件路径
            String cosKey = "knowledge/" + kbId + "/" + fileName;

            // 上传文件到COS
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());

            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    bucketName, cosKey, file.getInputStream(), metadata);
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

            // 创建文件记录
            KnowledgeFilesDO fileDO = new KnowledgeFilesDO();
            fileDO.setId("file_" + UUID.randomUUID().toString().replace("-", ""));
            fileDO.setKnowledge_id(kbId);
            fileDO.setName(originalFilename);
            fileDO.setPath(cosKey);
            fileDO.setSize(file.getSize());
            fileDO.setType(file.getContentType());
            fileDO.setCreated_at(LocalDateTime.now());

            // 保存文件记录到数据库
            knowledgeFilesDAO.insert(fileDO);

            return fileDO;
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }


    // ------------------- 新增：管理员-创建系统知识库 -------------------
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemKnowledgeBasesDO createSystemKnowledgeBase(String name, String description, String email, MultipartFile[] files) {
        // 1. 权限校验：非管理员抛异常
        if (!AuthUtil.isAdmin(email)) {
            throw new RuntimeException("非管理员无权限创建系统知识库");
        }
        // 2. 生成系统知识库ID
        String systemKbId = UUID.randomUUID().toString().replace("-", "");
        // 3. 保存系统知识库
        SystemKnowledgeBasesDO systemKb = new SystemKnowledgeBasesDO();
        systemKb.setId(systemKbId);
        systemKb.setName(name);
        systemKb.setDescription(description);
        systemKb.setDoc_count(files.length);
        systemKb.setCreated_at(LocalDateTime.now());
        systemKnowledgeBasesDAO.insert(systemKb);
        // 4. 上传文件到COS并保存系统文件记录
        for (MultipartFile file : files) {
            try {
                // 4.1 上传文件到COS（路径：system_kb/{systemKbId}/{文件名}）
                String cosFilePath = "system_kb/" + systemKbId + "/" + UUID.randomUUID() + "_" + file.getOriginalFilename();
                cosClient.putObject(bucketName, cosFilePath, file.getInputStream(), null);
                // 4.2 保存系统文件记录
                SystemKnowledgeFilesDO systemFile = new SystemKnowledgeFilesDO();
                systemFile.setId(UUID.randomUUID().toString().replace("-", ""));
                systemFile.setSystem_kb_id(systemKbId);
                systemFile.setName(file.getOriginalFilename());
                systemFile.setPath(cosFilePath);
                systemFile.setSize(file.getSize());
                systemFile.setType(file.getContentType());
                systemFile.setCreated_at(LocalDateTime.now());
                systemKnowledgeFilesDAO.insert(systemFile);
            } catch (IOException e) {
                throw new RuntimeException("系统知识库文件上传失败：" + e.getMessage());
            }
        }
        // 5. 返回带文件列表的系统知识库
        systemKb.setFiles(systemKnowledgeFilesDAO.selectBySystemKbId(systemKbId));
        return systemKb;
    }

    // ------------------- 新增：管理员-上传文件到系统知识库 -------------------
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemKnowledgeFilesDO uploadFileToSystemKb(String systemKbId, String email, MultipartFile file) {
        // 1. 权限校验
        if (!AuthUtil.isAdmin(email)) {
            throw new RuntimeException("非管理员无权限操作系统知识库");
        }
        // 2. 校验系统知识库是否存在
        SystemKnowledgeBasesDO systemKb = systemKnowledgeBasesDAO.selectById(systemKbId);
        if (systemKb == null) {
            throw new RuntimeException("系统知识库不存在");
        }
        try {
            // 3. 上传文件到COS
            String cosFilePath = "system_kb/" + systemKbId + "/" + UUID.randomUUID() + "_" + file.getOriginalFilename();
            cosClient.putObject(bucketName, cosFilePath, file.getInputStream(), null);
            // 4. 保存系统文件记录
            SystemKnowledgeFilesDO systemFile = new SystemKnowledgeFilesDO();
            systemFile.setId(UUID.randomUUID().toString().replace("-", ""));
            systemFile.setSystem_kb_id(systemKbId);
            systemFile.setName(file.getOriginalFilename());
            systemFile.setPath(cosFilePath);
            systemFile.setSize(file.getSize());
            systemFile.setType(file.getContentType());
            systemFile.setCreated_at(LocalDateTime.now());
            systemKnowledgeFilesDAO.insert(systemFile);
            // 5. 更新系统知识库文件数量
            systemKb.setDoc_count(systemKb.getDoc_count() + 1);
            systemKnowledgeBasesDAO.updateDocCount(systemKb);
            return systemFile;
        } catch (IOException e) {
            throw new RuntimeException("系统知识库文件上传失败：" + e.getMessage());
        }
    }

    // ------------------- 新增：管理员-删除系统知识库 -------------------
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteSystemKnowledgeBase(String systemKbId, String email) {
        // 1. 权限校验
        if (!AuthUtil.isAdmin(email)) {
            throw new RuntimeException("非管理员无权限删除系统知识库");
        }
        // 2. 校验系统知识库是否存在
        SystemKnowledgeBasesDO systemKb = systemKnowledgeBasesDAO.selectById(systemKbId);
        if (systemKb == null) {
            throw new RuntimeException("系统知识库不存在");
        }
        // 3. 级联删除系统知识库的文件（COS+数据库）
        List<SystemKnowledgeFilesDO> files = systemKnowledgeFilesDAO.selectBySystemKbId(systemKbId);
        for (SystemKnowledgeFilesDO file : files) {
            // 3.1 删除COS文件
            cosClient.deleteObject(new DeleteObjectRequest(bucketName, file.getPath()));
            // 3.2 删除数据库文件记录
            systemKnowledgeFilesDAO.deleteById(file.getId());
        }
        // 4. 删除系统知识库
        systemKnowledgeBasesDAO.deleteById(systemKbId);
        return true;
    }

    // ------------------- 新增：管理员-删除系统知识库文件 -------------------
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteSystemKbFile(String systemKbId, String fileId, String email) {
        // 1. 权限校验
        if (!AuthUtil.isAdmin(email)) {
            throw new RuntimeException("非管理员无权限删除系统知识库文件");
        }
        // 2. 校验文件是否存在
        SystemKnowledgeFilesDO file = systemKnowledgeFilesDAO.selectById(fileId);
        if (file == null || !file.getSystem_kb_id().equals(systemKbId)) {
            throw new RuntimeException("系统知识库文件不存在");
        }
        // 3. 删除COS文件
        cosClient.deleteObject(new DeleteObjectRequest(bucketName, file.getPath()));
        // 4. 删除数据库文件记录
        systemKnowledgeFilesDAO.deleteById(fileId);
        // 5. 更新系统知识库文件数量
        SystemKnowledgeBasesDO systemKb = systemKnowledgeBasesDAO.selectById(systemKbId);
        systemKb.setDoc_count(systemKb.getDoc_count() - 1);
        systemKnowledgeBasesDAO.updateDocCount(systemKb);
        return true;
    }

    // ------------------- 新增：管理员-获取系统知识库文件列表 -------------------
    @Override
    public List<SystemKnowledgeFilesDO> getFilesBySystemKbId(String systemKbId) {
        return systemKnowledgeFilesDAO.selectBySystemKbId(systemKbId);
    }
}
